const BodyCore = (function () {
  const DATA_INDEX_CONCAT_CHAR = "<>";
  const B = {
    keyJoin: function (...args) {
      return args.filter((i) => typeof i !== "undefined").join(DATA_INDEX_CONCAT_CHAR);
    },

    // 树形转为list
    treeFlat: function (tree) {
      const res = [];
      let stack = tree;
      while (stack.length > 0) {
        const item = stack.shift();
        item.hasChildren = !!(item.children && item.children.length > 0);
        res.push(item);
        if (item.children && item.children.length > 0) {
          stack = stack.concat(item.children);
        }
      }
      return res;
    },

    // 获取渲染字段列表
    getRenderColumns: function (columns) {
      const fields = B.treeFlat(JSON.parse(JSON.stringify(columns)));
      const tableFields = fields.filter((field) => !field.hasChildren).sort((a, b) => a.sort - b.sort);
      return tableFields;
    },

    /**
     * 序列化数据
     * @param {*} columns 
     * @param {*} data 
     * @returns 
     */
    parseData: function (columns, data) {
      const result = [];
      // 遍历数据
      for (let i = 0, len = data.length; i < len; i++) {
        let resRow = {};
        let dataRow = data[i];
        for (let j = 0; j < dataRow.length; j++) {
          const dataIndex = columns[j].dataIndex;
          // 判断是否位合并数据
          if (Array.isArray(dataRow[j])) {
            for (let k = 0; k < dataRow[j].length; k++) {
              const key = B.keyJoin(dataIndex, ...dataRow[j][k].slice(1));
              resRow[key] = dataRow[j][k][0];
            }
          } else {
            resRow[dataIndex] = dataRow[j];
          }
        }
        result.push(resRow);
      }
      return result;
    },

    /**
     * 获取单元格合并信息
     * @param {array} columns 字段列表 
     * @param {array} data 数据
     * @returns 
     */
    getCellMerge: function (columns, data) {
      const cellMap = {};
      const createCellMergeItem = function (start, end, rowspan, value) {
        return { startIndex: start, endIndex: end, rowspan, value: value };
      };
      const diffParent = function (rowIndex, prevRowIndex, columnIndex) {
        let rowRes = [];
        let prevRowRes = [];
        // 依次从查询字段对比到第一个字段，是否一样；
        while (columnIndex >= 0) {
          const col = columns[columnIndex];
          rowRes.unshift(data[rowIndex][col.dataIndex]);
          prevRowRes.unshift(data[prevRowIndex][col.dataIndex]);
          columnIndex--;
        }
        return rowRes.join("") === prevRowRes.join("");
      };
      const setMergeInfo = function (dataIndex, prev, rowspan) {
        // 找当跟上一个一个组的成员，设置偏移数量
        cellMap[dataIndex] = cellMap[dataIndex].map((row, idx) => {
          if (row.startIndex === prev.startIndex && row.value === prev.value) {
            row.rowspanIndex = idx - row.startIndex;
            row.endIndex = prev.startIndex + rowspan - 1;
            row.rowspan = rowspan;
          }
          return row;
        });
      };
      for (let j = 0; j < columns.length; j++) {
        const { dataIndex } = columns[j];
        let rowspan = 1;
        let startIndex = 0;
        for (let i = 0; i < data.length; i++) {
          const rowValue = data[i][dataIndex];
          if (!cellMap[dataIndex]) {
            cellMap[dataIndex] = [];
          }
          const diffCur = i > 0 && rowValue !== undefined && rowValue === data[i - 1][dataIndex];
          const diffParents = i > 0 && (j === 0 ? true : diffParent(i, i - 1, j));
          /**
           * 1、对比当前字段与上一条记录的同一字段是否一样；
           * 2、对比当前的上n个字段与上一条的记录的上n个字段是否一样（简单的说就是判断是否在一个分组下）
           * 两个条件都满足情况下合并；
           */
          if (diffCur && diffParents) {
            rowspan++;
            // 是否为最后一条数据
          } else {
            // 如果与上一个值不一样, 则给当前的上一条数据设置合并信息
            setMergeInfo(dataIndex, cellMap[dataIndex][i - 1], rowspan);
            startIndex = i;
            rowspan = 1;
          }
          cellMap[dataIndex].push(createCellMergeItem(startIndex, i, rowspan, rowValue));
          // 是否为最后一条数据
          if (i === data.length - 1) {
            setMergeInfo(dataIndex, cellMap[dataIndex][i], rowspan);
          }
        }
      }
      return cellMap;
    },
  };

  /**
   * 创建表体
   * @param {*} columnTree
   * @param {*} dataSource
   */
  function create(columns, dataSource) {
    const renderColumns = B.getRenderColumns(columns);
    const dataList = B.parseData(columns, dataSource);
    const cellMerge = B.getCellMerge(renderColumns, dataList);
    return { dataList, renderColumns, cellMerge };
  }
  return { create: create };
})();
